﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;


namespace SharpErp.Data.Common.Context
{
    public class SharpErpDbContext : DbContext
    {
        public  delegate View.CompanyStaffView GetCurrentStaffDelegate();

        public static GetCurrentStaffDelegate GetCurrentStaff { get; set; }

        public static View.CompanyStaffView GetCurrentStaffView()
        {
            if (GetCurrentStaff == null) return null;
            return GetCurrentStaff.Invoke();
        }

        public DbSet<Entity.ItemClass> ItemClasses{ get; set; }
        
        public DbSet<Entity.KVEntity> KVEntities{get;set;}
        
        public DbSet<Entity.CustomerSecondClass> CustomerSencodClasEntities{get;set;}
        
        public DbSet<Entity.CustomerThirdClass> CustomerThirdClasEntities{get;set;}

        public DbSet<Entity.ItemSevenClass> ItemSevenClasses { get; set; }

        public DbSet<Entity.ItemEightClass> ItemEightClasses { get; set; }

        public DbSet<Entity.ItemNineClass> ItemNineClasses { get; set; }

        public DbSet<Entity.ProductionSevenClass> ProductionSevenClasses { get; set; }

        public DbSet<Entity.ProductionEightClass> ProductionEightClasses { get; set; }

        public DbSet<Entity.ProductionNineClass> ProductionNineClasses { get; set; }

        public DbSet<Entity.ProductionTenClass> ProductionTenClasses { get; set; }
        
        public DbSet<Entity.MaterialSevenClass> MaterialSevenClasses { get; set; }

        public DbSet<Entity.MaterialEightClass> MaterialEightClasses { get; set; }

        public DbSet<Entity.MaterialNineClass> MaterialNineClasses { get; set; }
        
        public DbSet<Entity.GoodsMaterialClass> GoodsMaterialClasses { get; set; }

        public DbSet<Entity.CustomerGoodsClass> CustomerGoodsClasses { get; set; }

        public DbSet<Entity.Department.CompanyStaff> CompanyStaffs { get; set; }

        public DbSet<Entity.Department.CompanyAsset> CompanyAssets { get; set; }
        
		protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
		{
			optionsBuilder.UseSqlite( "Filename=" + System.Environment.CurrentDirectory + "\\test.db3");
            //optionsBuilder.UseNpgsql("User ID=admin;Password=admin;Host=localhost;Port=5432;Database=sharperp;Pooling=true;");
			base.OnConfiguring(optionsBuilder);
		}
		
		protected override void OnModelCreating(ModelBuilder modelBuilder)
		{
			base.OnModelCreating(modelBuilder);
		}
		
        private IQueryable<T> FilterSetAccount<T>(IQueryable<T> query ) where T:Common.Entity.BaseEntity
        {
            var staff = GetCurrentStaffView();
            if(staff == null)
            {
                query = query.Where(p => p.SetId == 0 && p.SetShare == 0);
            }else
            {
                if (staff.SetShare > 0) 
                {
                    query = query.Where(p => p.SetShare == staff.SetShare);
                    if (staff.SetId > 0) query = query.Where(p => p.SetId == staff.SetId);
                }else{
                    query = query.Where(p => p.SetShare == 0);

                }
            }
            return query;
        }

		public IQueryable<T> All<T>(DbSet<T> dbSet) where T : Common.Entity.BaseEntity
		{
			return FilterSetAccount(dbSet.Where(p=>(p.SystemFlag & Common.Entity.BaseEntity.SYS_FLAG_DELETE) == 0));
		}
		
		public T[] AllArray<T>(DbSet<T> dbSet) where T : Common.Entity.BaseEntity
		{
			return FilterSetAccount(dbSet.Where(p=>(p.SystemFlag &  Common.Entity.BaseEntity.SYS_FLAG_DELETE) == 0)).ToArray<T>();
		}
		
		public T SelectOne<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
		{
			return All<T>(dbSet).FirstOrDefault(predicate);
		}
		
		public List<T> SelectAll<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
		{
			return All<T>(dbSet).Where(predicate).ToList<T>();
		}
		
		public void Delete<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
		{
			var array = All<T>(dbSet).Where(predicate).ToArray<T>();
			foreach(var item in array)
			{
				item.SystemFlag = item.SystemFlag | Common.Entity.BaseEntity.SYS_FLAG_DELETE;
			}
			this.SaveChanges();
		}
		
		public T Add<T>(DbSet<T> dbSet, T data) where T : Common.Entity.BaseEntity
		{
		    data.CreateTime = data.LastModifyTime = DateTime.Now;
            var staff = GetCurrentStaffView();
            if(staff != null)
            {
                data.SetId = staff.SetId;
                data.SetShare = staff.SetShare;
            }
			var result = dbSet.Add(data);
			this.SaveChanges();
            return result.Entity;
		}
		
		public void Update<T>(DbSet<T> dbSet, T data) where T : Common.Entity.BaseEntity
		{
            data.LastModifyTime = DateTime.Now;
			dbSet.Update(data);
			this.SaveChanges();
		}
		
		public void Clear<T>(DbSet<T> dbSet, Expression<Func<T, bool>> predicate) where T : Common.Entity.BaseEntity
		{
			var array = FilterSetAccount(dbSet.Where(predicate)).ToArray<T>();
			dbSet.RemoveRange(array);
			this.SaveChanges();
		}
	}
}

